package com.yyfax.pay.quartz.jobs;

import java.util.Date;

import com.yyfax.pay.order.data.service.ProtocolPayService;
import org.apache.commons.lang3.StringUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.spring.ApplicationContextHolder;
import com.yyfax.pay.common.constants.PayConstants;
import com.yyfax.pay.common.enums.NotifyTaskTypeEnum;
import com.yyfax.pay.common.enums.PayStepEnum;
import com.yyfax.pay.common.enums.TaskStateEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.order.data.service.NotifyTaskService;
import com.yyfax.pay.order.model.po.NotifyTaskPO;
import com.yyfax.pay.order.model.vo.PayOrderVO;
import com.yyfax.pay.order.service.AuthService;
import com.yyfax.pay.order.service.PayService;
import com.yyfax.pay.order.service.PayoutService;
import com.yyfax.pay.quartz.model.vo.DynamicJobVO;
import org.springframework.stereotype.Component;

/**
 * 回调支付订单任务
 *
 * @author jiangmy
 * @date 2017-04-18 15:53:28
 * @since v1.0.0
 */
@Component
public class NotifyPayOrderJob implements Job {

	protected Logger logger = LoggerFactory.getLogger(getClass());

	// services
	private NotifyTaskService taskService;
	private PayService payService;

	private PayoutService payoutService;

	private AuthService authService;

	private ProtocolPayService protocolPayService;

	// biz data
	private NotifyTaskPO task;

	private PayConstants payConstants;

	public void preInit(JobExecutionContext context) throws YYPayException {
		// services
		taskService = ApplicationContextHolder.getBean(NotifyTaskService.class);
		payService = ApplicationContextHolder.getBean(PayService.class);
		payoutService = ApplicationContextHolder.getBean(PayoutService.class);
		authService = ApplicationContextHolder.getBean(AuthService.class);
		payConstants = ApplicationContextHolder.getBean(PayConstants.class);
		protocolPayService = ApplicationContextHolder.getBean(ProtocolPayService.class);
	}

	@Override
	public void execute(JobExecutionContext context) throws JobExecutionException {
		logger.info("执行任务:{}", context);
		// 初始化环境
		try {
			preInit(context);
		} catch (Exception e) {
			logger.error(e.getMessage());
			return;
		}

		boolean isNotify = false; // 异步通知结果

		// 初始化数据
		try {
			Object orderObj = context.getMergedJobDataMap().get(DynamicJobVO.ORDER_KEY);
			if (orderObj == null) {
				logger.warn("【定时任务失败】订单信息为空 {}", context.getJobDetail().getKey());
				return;
			}
			task = (NotifyTaskPO) orderObj;

			if (NotifyTaskTypeEnum.PAY.isValue(task.getType())) {
				PayOrderVO order = payService.notifyPayOrder(task);
				if (order != null && order.getStepSuccess(PayStepEnum.STEP5_NOTIFY) != null) {
					isNotify = true;
				}
			}
			//代付暂时作废，edit by buyi,since 1.3.0
			// else if (NotifyTaskTypeEnum.PAYOUT.isValue(task.getType())) {
			// PayoutOrderVO payoutOrderVO =
			// payoutService.notifyPayoutOrder(task);
			// if (payoutOrderVO != null &&
			// payoutOrderVO.getStep(PayoutStepEnum.STEP3_NOTIFY) != null) {
			// isNotify = true;
			// }
			//
			// }

			else if (NotifyTaskTypeEnum.AUTHENTICATION.isValue(task.getType())) {
				String result = authService.notifyAuthOrder(task);
				if (StringUtils.isNotBlank(result)) {
					isNotify = true;
				}
			} else if (NotifyTaskTypeEnum.PROTOCOL_PAY.isValue(task.getType())) {
				String result = protocolPayService.notifyProtocolOrder(task);
				if (StringUtils.isNotBlank(result)) {
					isNotify = true;
				}
			}

		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}

		// 更新task
		try {
			task.setLastTime(DateUtil.getCurrentDateTime());
			task.setNextTime(DateUtil.datetime2Str(calculateNextTime(task.getOptNo())));
			task.setOptNo(task.getOptNo() + 1);

			// 任务已完成
			if (isNotify) {
				task.setState(TaskStateEnum.SUCCESS.getValue());
				task.setRemark("回调成功");
				return;
			}
			// 超次或者超时
			if (task.getOptNo() >= task.getMaxNo()
					|| (task.getEndTime() != null && task.getEndTime().compareTo(DateUtil.getCurrentDateTime()) <= 0)) {
				task.setState(TaskStateEnum.FAILED.getValue());
				task.setRemark("达到最大回调次数或时间");
				return;
			}

		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		} finally {
			try {
				// taskService.updateTask(task);
				taskService.updateTaskByMerchantAndOrderId(task);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		// 刷新任务
		try {
			refreshTask();
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 计算下次执行时间
	 *
	 * @author buyi
	 * @date 2017-05-13 11:26:14
	 * @since v1.0.0
	 * @param optNo 从零开始
	 * @return
	 */
	public Date calculateNextTime(int optNo) {
		int interval = payConstants.getNextTimeInterval(optNo);

		return DateUtil.addSecond(new Date(), interval);
	}

	public void refreshTask() throws YYPayException {
		if (!TaskStateEnum.ACTIVE.isValue(task.getState())) {
			return;
		}
		DynamicJobVO dynamicJob = new DynamicJobVO(task);
		try {
			// 查询代付订单
			dynamicJob.target(getClass());
			dynamicJob.addOrderData(task);
			dynamicJob.cronExpression(DateUtil.date2Str(DateUtil.str2DateTime(task.getNextTime()), "s m H d M ? yyyy")); // "0 15 10 * * ? 2015"
			// 2015年的每天早上10：15触发
			com.yyfax.pay.quartz.dynamic.DynamicSchedulerFactory.updateJob(dynamicJob);
		} catch (Exception e) {
			logger.error("【添加任务】", e);
		} finally {
			logger.info("【添加任务】{}", task);
			logger.info("【添加Quartz】{}", dynamicJob);
		}
	}
}
